package jwt_token

import (
	"errors"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"strings"
	"time"
	"vpn/app/global"
	"vpn/app/global/consts"
	"vpn/app/global/my_errors"
)

type CustomClaims struct {
	UserName string `json:"username"`
	jwt.StandardClaims
}

// CreateToken 生成一个token
func (claims *CustomClaims) CreateToken() (string, error) {
	// 生成jwt格式的header、claims 部分
	tokenPartA := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	// 继续添加秘钥值，生成最后一部分
	return tokenPartA.SignedString([]byte(global.JwtConf.JwtTokenSignKey))
}

// -----------------------------允许token过期----------------------------------
// 解析Token
//
//	func ParseToken(ctx *gin.Context) (*CustomClaims, error) {
//		tokenString := strings.TrimPrefix(ctx.GetHeader("Authorization"), "Bearer ")
//		token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { return global.JwtConf.JwtTokenSignKey, nil })
//		log.Info(token)
//		if token == nil {
//			return nil, errors.New(my_errors.ErrorsTokenInvalid)
//		}
//		if err != nil {
//			if ve, ok := err.(*jwt.ValidationError); ok {
//				if ve.Errors&jwt.ValidationErrorMalformed != 0 {
//					return nil, errors.New(my_errors.ErrorsTokenMalFormed)
//				} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
//					return nil, errors.New(my_errors.ErrorsTokenNotActiveYet)
//				} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
//					// 如果 TokenExpired ,只是过期（格式都正确），我们认为他是有效的，接下可以允许刷新操作
//					token.Valid = true
//					goto labelHere
//				} else {
//					return nil, errors.New(my_errors.ErrorsTokenInvalid)
//				}
//			}
//		}
//
// labelHere:
//
//		if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
//			return claims, nil
//		}
//		return nil, errors.New(my_errors.ErrorsTokenInvalid)
//	}

// ***************** token不允许过期 *******************
func ParseToken(ctx *gin.Context) (*CustomClaims, error) {
	tokenString := strings.TrimPrefix(ctx.GetHeader(consts.JwtTokenHeaderKey), consts.JwtTokenPrefix)
	token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(global.JwtConf.JwtTokenSignKey), nil })
	fmt.Println(err)
	if token == nil {
		return nil, errors.New(my_errors.ErrorsTokenInvalid)
	}
	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, errors.New(my_errors.ErrorsTokenMalFormed)
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, errors.New(my_errors.ErrorsTokenNotActiveYet)
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				return nil, errors.New(my_errors.ErrorsTokenExpired)
			} else {
				return nil, errors.New(my_errors.ErrorsTokenInvalid)
			}
		}
	}
	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
		return claims, nil
	}
	return nil, errors.New(my_errors.ErrorsTokenInvalid)
}

// 更新token
func (claims *CustomClaims) RefreshToken(extraAddSeconds int64) (string, error) {
	claims.ExpiresAt = time.Now().Unix() + extraAddSeconds
	return claims.CreateToken()
}

func ValidateJwtToken(ctx *gin.Context) (*CustomClaims, int) {
	if customClaims, err := ParseToken(ctx); err == nil {
		if time.Now().Unix() < customClaims.ExpiresAt-global.JwtConf.JwtExpireAt/2 {
			// token有效
			return customClaims, consts.JwtTokenOK
		} else {
			// 即将过期的token
			return customClaims, consts.JwtTokenCloseExpire
		}
	} else {
		// 无效的token
		return nil, consts.JwtTokenInvalid
	}
}
